package cn.iocoder.yudao.module.book.service.checkIn;

import cn.iocoder.yudao.module.book.controller.app.lock.vo.AppCheckInSaveReqVO;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import cn.iocoder.yudao.module.book.controller.admin.checkIn.vo.*;
import cn.iocoder.yudao.module.book.dal.dataobject.checkIn.CheckInDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.book.dal.mysql.checkIn.CheckInMapper;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.book.enums.ErrorCodeConstants.*;

/**
 * 打卡 Service 实现类
 *
 * @author xi
 */
@Service
@Validated
public class CheckInServiceImpl implements CheckInService {

    @Resource
    private CheckInMapper checkInMapper;

    @Override
    public Integer createCheckIn(CheckInSaveReqVO createReqVO) {
        // 插入
        CheckInDO checkIn = BeanUtils.toBean(createReqVO, CheckInDO.class);
        checkInMapper.insert(checkIn);
        // 返回
        return checkIn.getClockId();
    }

    @Override
    public Integer AppcreateCheckIn(AppCheckInSaveReqVO createReqVO) {
        CheckInDO checkIn = BeanUtils.toBean(createReqVO, CheckInDO.class);
        
        // 验证打卡类型和班级ID的关系
        if (createReqVO.getCheckInType() == 2 && createReqVO.getClassId() == null) {
            throw exception(REQUEST_PARAMS_NOT_VALID);
        }
        
        // 查询今日同类型是否已经打卡（同类型一天只能打卡一次）
        if(checkInMapper.selectNowDayByType(createReqVO.getUserId(), createReqVO.getCreateTime(), createReqVO.getCheckInType())){
            throw exception(CHECK_IN_ALREADY_EXISTS_TODAY);
        }else{
            // 插入
//            checkIn.setCreateTime(LocalDateTime.now());
            checkInMapper.insert(checkIn);
        }
        // 返回
        return checkIn.getClockId();
    }

    @Override
    public void updateCheckIn(CheckInSaveReqVO updateReqVO) {
        // 校验存在
        validateCheckInExists(updateReqVO.getClockId());
        // 更新
        CheckInDO updateObj = BeanUtils.toBean(updateReqVO, CheckInDO.class);
        checkInMapper.updateById(updateObj);
    }

    @Override
    public void deleteCheckIn(Integer id) {
        // 校验存在
        validateCheckInExists(id);
        // 删除
        checkInMapper.deleteById(id);
    }

    private void validateCheckInExists(Integer id) {
        if (checkInMapper.selectById(id) == null) {
            throw exception(CHECK_IN_NOT_EXISTS);
        }
    }

    @Override
    public CheckInDO getCheckIn(Integer id) {
        return checkInMapper.selectById(id);
    }

    @Override
    public PageResult<CheckInDO> getCheckInPage(CheckInPageReqVO pageReqVO) {
        return checkInMapper.selectPage(pageReqVO);
    }

    @Override
    public Integer selectDayCount(Long userId) {
        return checkInMapper.selectDayCount(userId);
    }

    @Override
    public CheckInDO selectBook(Long userId, String time) {
        return checkInMapper.selectBook(userId, time);
    }

    @Override
    public Integer createStudyCheckIn(AppCheckInSaveReqVO createReqVO) {
        // 设置为学习打卡类型
        createReqVO.setCheckInType(1);
        createReqVO.setClassId(null); // 学习打卡不需要班级ID
        return AppcreateCheckIn(createReqVO);
    }

    @Override
    public Integer createClassCheckIn(AppCheckInSaveReqVO createReqVO) {
        // 设置为班级打卡类型
        createReqVO.setCheckInType(2);
        // 班级打卡必须有班级ID
        if (createReqVO.getClassId() == null) {
            throw exception(REQUEST_PARAMS_NOT_VALID);
        }
        return AppcreateCheckIn(createReqVO);
    }

    @Override
    public PageResult<CheckInDO> getClassCheckInPage(Integer classId, CheckInPageReqVO pageReqVO) {
        return checkInMapper.selectPage(pageReqVO, new LambdaQueryWrapperX<CheckInDO>()
                .eq(CheckInDO::getClassId, classId)
                .eq(CheckInDO::getCheckInType, 2) // 班级打卡
                .eqIfPresent(CheckInDO::getUserId, pageReqVO.getUserId())
                .eqIfPresent(CheckInDO::getBookList, pageReqVO.getBookList())
                .eqIfPresent(CheckInDO::getContent, pageReqVO.getContent())
                .eqIfPresent(CheckInDO::getDayCount, pageReqVO.getDayCount())
                .betweenIfPresent(CheckInDO::getCreateTime, pageReqVO.getCreateTime())
                .orderByDesc(CheckInDO::getClockId));
    }

    @Override
    public PageResult<CheckInDO> getLatestCheckInPage(CheckInPageReqVO pageReqVO) {
        return checkInMapper.selectPage(pageReqVO, new LambdaQueryWrapperX<CheckInDO>()
                .eq(CheckInDO::getCheckInType, 1) // 学习打卡
                .eqIfPresent(CheckInDO::getUserId, pageReqVO.getUserId())
                .eqIfPresent(CheckInDO::getBookList, pageReqVO.getBookList())
                .eqIfPresent(CheckInDO::getContent, pageReqVO.getContent())
                .eqIfPresent(CheckInDO::getDayCount, pageReqVO.getDayCount())
                .betweenIfPresent(CheckInDO::getCreateTime, pageReqVO.getCreateTime())
                .orderByDesc(CheckInDO::getCreateTime)); // 按创建时间降序
    }

    @Override
    public PageResult<CheckInDO> getFollowingCheckInPage(List<Long> userIds, CheckInPageReqVO pageReqVO) {
        if (userIds == null || userIds.isEmpty()) {
            return new PageResult<>(new ArrayList<>(), 0L);
        }
        
        return checkInMapper.selectPage(pageReqVO, new LambdaQueryWrapperX<CheckInDO>()
                .eq(CheckInDO::getCheckInType, 1) // 学习打卡
                .in(CheckInDO::getUserId, userIds) // 关注的用户ID列表
                .eqIfPresent(CheckInDO::getBookList, pageReqVO.getBookList())
                .eqIfPresent(CheckInDO::getContent, pageReqVO.getContent())
                .eqIfPresent(CheckInDO::getDayCount, pageReqVO.getDayCount())
                .betweenIfPresent(CheckInDO::getCreateTime, pageReqVO.getCreateTime())
                .orderByDesc(CheckInDO::getCreateTime)); // 按创建时间降序
    }

    @Override
    public PageResult<CheckInDO> getUserCheckInPage(Long userId, CheckInPageReqVO pageReqVO) {
        return checkInMapper.selectPage(pageReqVO, new LambdaQueryWrapperX<CheckInDO>()
                .eq(CheckInDO::getCheckInType, 1) // 学习打卡
                .eq(CheckInDO::getUserId, userId) // 指定用户
                .eqIfPresent(CheckInDO::getBookList, pageReqVO.getBookList())
                .eqIfPresent(CheckInDO::getContent, pageReqVO.getContent())
                .eqIfPresent(CheckInDO::getDayCount, pageReqVO.getDayCount())
                .betweenIfPresent(CheckInDO::getCreateTime, pageReqVO.getCreateTime())
                .orderByDesc(CheckInDO::getCreateTime)); // 按创建时间降序
    }

}